---
title: SQL
description: 插件提供了一个接口，让前端可以通过 sqlx 与 SQL 数据库进行通信
plugin: sql
---

import PluginLinks from '@components/PluginLinks.astro';
import Compatibility from '@components/plugins/Compatibility.astro';

import { Tabs, TabItem } from '@astrojs/starlight/components';
import CommandTabs from '@components/CommandTabs.astro';

<PluginLinks plugin={frontmatter.plugin} />

这个插件提供了一个接口，让前端可以通过 [sqlx](https://github.com/launchbadge/sqlx) 与 SQL 数据库进行通信。
它支持 SQLite、MySQL 和 PostgreSQL 驱动程序，通过 Cargo 特性来启用。

## Supported Platforms

<Compatibility plugin={frontmatter.plugin} />

## 安装

首先，在你的 `Cargo.toml` 文件中添加以下内容来安装插件。

<Tabs>
  <TabItem label="crates.io">
```toml title="src-tauri/Cargo.toml"
[dependencies.tauri-plugin-sql]
features = ["sqlite"] # or "postgres", or "mysql"
version = "2.0.0"
```
  </TabItem>
  <TabItem label="Git">

```toml title="src-tauri/Cargo.toml"
[dependencies.tauri-plugin-sql]
features = ["sqlite"] # or "postgres", or "mysql"
git = "https://github.com/tauri-apps/plugins-workspace"
branch = "v2"
```

  </TabItem>
</Tabs>

然后，你必须使用你喜欢的 JavaScript 包管理器添加 JavaScript Guest 绑定。

<Tabs>
  <TabItem label="npm.io">
    <CommandTabs
      npm="npm add @tauri-apps/plugin-sql"
      yarn="yarn add @tauri-apps/plugin-sql"
      pnpm="pnpm add @tauri-apps/plugin-sql"
      bun="bun add @tauri-apps/plugin-sql"
    />
  </TabItem>
  <TabItem label="Git">
    <CommandTabs
      npm="npm add https://github.com/tauri-apps/tauri-plugin-sql#v2"
      yarn="yarn add https://github.com/tauri-apps/tauri-plugin-sql#v2"
      pnpm="pnpm add https://github.com/tauri-apps/tauri-plugin-sql#v2"
      bun="bun add https://github.com/tauri-apps/tauri-plugin-sql#v2"
    />
  </TabItem>
</Tabs>

## 用法

首先，你需要在 Tauri 中注册插件：

```rust title="src-tauri/src/main.rs" ins={3}
fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_sql::Builder::default().build())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
```

之后，所有插件的 API 都可以通过 JavaScript Guest 绑定使用。

<Tabs syncKey="SQLvariant">
  <TabItem label="SQLite">

这个路径是相对于 `tauri::api::path::BaseDirectory::App` 的。

```javascript
import Database from '@tauri-apps/plugin-sql';
const db = await Database.load('sqlite:test.db');
await db.execute('INSERT INTO ...');
```

  </TabItem>
  <TabItem label="MySQL">

```javascript
import Database from '@tauri-apps/plugin-sql';
const db = await Database.load('mysql://user:pass@host/database');
await db.execute('INSERT INTO ...');
```

  </TabItem>
  <TabItem label="PostgreSQL">

```javascript
import Database from '@tauri-apps/plugin-sql';
const db = await Database.load('postgres://postgres:password@localhost/test');
await db.execute('INSERT INTO ...');
```

  </TabItem>
</Tabs>

## 语法

我们使用 [sqlx](https://docs.rs/sqlx/latest/sqlx/) 作为底层库并采用它们的查询语法。

<Tabs syncKey="SQLvariant">
  <TabItem label="SQLite">
在替换查询数据时使用 "$#" 语法

```javascript
const result = await db.execute(
  'INSERT into todos (id, title, status) VALUES ($1, $2, $3)',
  [todos.id, todos.title, todos.status]
);

const result = await db.execute(
  'UPDATE todos SET title = $1, status = $2 WHERE id = $3',
  [todos.title, todos.status, todos.id]
);
```

  </TabItem>
  <TabItem label="MySQL">
在替换查询数据时使用 "?" 语法

```javascript
const result = await db.execute(
  'INSERT into todos (id, title, status) VALUES (?, ?, ?)',
  [todos.id, todos.title, todos.status]
);

const result = await db.execute(
  'UPDATE todos SET title = ?, status = ? WHERE id = ?',
  [todos.title, todos.status, todos.id]
);
```

  </TabItem>
  <TabItem label="PostgreSQL">
在替换查询数据时使用 "$#" 语法

```javascript
const result = await db.execute(
  'INSERT into todos (id, title, status) VALUES ($1, $2, $3)',
  [todos.id, todos.title, todos.status]
);

const result = await db.execute(
  'UPDATE todos SET title = $1, status = $2 WHERE id = $3',
  [todos.title, todos.status, todos.id]
);
```

  </TabItem>
</Tabs>

## 迁移

这个插件支持数据库迁移，允许你管理数据库模式随时间的变化。

### 定义迁移

迁移在 Rust 中使用 [`Migration`](https://docs.rs/tauri-plugin-sql/latest/tauri_plugin_sql/struct.Migration.html) 结构体定义。
每个迁移都应该包含唯一的版本号、描述、要执行的 SQL 和迁移类型（向上或向下）。

迁移的例子：

```rust
use tauri_plugin_sql::{Migration, MigrationKind};

let migration = Migration {
    version: 1,
    description: "create_initial_tables",
    sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);",
    kind: MigrationKind::Up,
};
```

### 向插件构建器添加迁移

迁移用插件提供的 [`Builder`](https://docs.rs/tauri-plugin-sql/latest/tauri_plugin_sql/struct.Builder.html) 结构体注册。
使用 `add_migrations` 方法将迁移添加到特定数据库连接的插件中。

添加迁移的例子：

```rust title="src-tauri/src/main.rs" {1} {6-11} {17}
use tauri_plugin_sql::{Builder, Migration, MigrationKind};

fn main() {
    let migrations = vec![
        // Define your migrations here
        Migration {
            version: 1,
            description: "create_initial_tables",
            sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);",
            kind: MigrationKind::Up,
        }
    ];

    tauri::Builder::default()
        .plugin(
            tauri_plugin_sql::Builder::default()
                .add_migrations("sqlite:mydatabase.db", migrations)
                .build(),
        )
        ...
}
```

### 应用迁移

迁移在插件初始化时自动应用。插件针对连接字符串指定的数据库运行这些迁移。确保迁移按照正确的顺序定义，并且是幂等的（可以安全运行多次）。

### 迁移管理

- **版本控制**：每个迁移必须有一个唯一的版本号。这对于确保迁移按正确的顺序应用至关重要。
- **幂等性**：编写迁移时，要确保它们能够安全重新运行，而不会导致错误或意外后果。
- **测试**：彻底测试迁移，确保它们按预期工作，并且不会损害数据库的完整性。
